/*
 * Copyright (C) 2000-2006 Sailing Group
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 */
package lfp.domain.utils;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;

import java.net.URL;

/**
 * <pre>
 * Developer: hhh
 * Date: 2006-8-26
 * </pre>
 * <p/>
 * <p/>
 * encapsulating of basic DB operation
 * According to Jch. PersistenceUtil
 */
public class HPersistenceUtil {
    private static Logger log = Logger.getLogger(PersistenceUtil.class);

    protected Configuration configuration;
    protected SessionFactory sessionFactory;
    private final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
    private final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>();

    /**
     * build PersistenceUtil from configPath
     *
     * @param configPath
     */
    public HPersistenceUtil(String configPath) {
        URL url = HPersistenceUtil.class.getResource(configPath);
        if (url == null) return;
        configuration = new AnnotationConfiguration().configure(url);
        sessionFactory = configuration.buildSessionFactory();
    }


    //-------------------------session functions---------------------------------
    public Session getSession() {
        Session s = threadSession.get();
        // Open a new Session, if this Thread has none yet
        if (s == null || !s.isOpen()) {
            s = sessionFactory.openSession();
            threadSession.set(s);
        }
        return s;
    }

    public void closeSession() {
        Session s = threadSession.get();
        threadSession.set(null);
        if (s != null && s.isOpen()) {
            try {
                s.close();
            } catch (HibernateException e) {
                log.error(e);
            }
        }
    }

    public void beginTransaction() {
        Transaction tx = threadTransaction.get();
        if (tx == null) {
            tx = getSession().beginTransaction();
            threadTransaction.set(tx);
        }
    }

    public void commitTransaction() {
        Transaction tx = threadTransaction.get();
        try {
            if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
                tx.commit();
            threadTransaction.set(null);
        } catch (HibernateException ex) {
            rollbackTransaction();
            throw ex;
        }
    }

    public void rollbackTransaction() {
        Transaction tx = threadTransaction.get();
        try {
            threadTransaction.set(null);
            if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
                tx.rollback();
            }
        } catch (HibernateException e) {
            log.error(e);
        } finally {
            closeSession();
        }
    }

    //==================================helper functions ====================
    public void buildSchema() {
        SchemaExport schemaExport = new SchemaExport(configuration);
        schemaExport.create(false, true);
    }

    public void dropSchema() {
        SchemaExport schemaExport = new SchemaExport(configuration);
        schemaExport.drop(false, true);
    }

    public void updateSchema() {
        SchemaUpdate schemaUpdate = new SchemaUpdate(configuration);
        schemaUpdate.execute(true, true);
    }
}
